<?php
/**
 * Note: 日统计
 */

namespace App\Models\Mongo\DailyLog;

use App\Traits\ModelTrait;
use App\Traits\MongoModelTrait;
use Jenssegers\Mongodb\Collection;

class HourStat extends Base
{
    use ModelTrait, MongoModelTrait;

    protected $table = 'hourStat';

    public $timestamps = false;

    protected $fillable = [
        'day',
        'hour',
        'source',
        'pay',
        'payCnt',
        'payUser',
        'withdraw',
        'withdrawCnt',
        'withdrawUser',
        'withdrawFirstAll',
        'withdrawFirstUserAll',
        'thirdExchange',
        'thirdExchangeCnt',
        'thirdExchangeUser',
        'thirdExchangeFirstAll',
        'thirdExchangeFirstUserAll',
        'registerUser',
        'registerUserAll',
        'loginUser',
        'loginUserAll',
        // 'hbChange',
        // 'hbChangeAll',
        'hbToBulletCost',
        'sceneRunningWater',
        'sceneRunningWaterAll',
        'cpaCost',
        'cpaCostAll',
        'payFirstOldUser24',
        'payFirstOldUser24All',
        'payFirstOldUser48',
        'payFirstOldUser48All',
    ];

    protected $casts = [
        'hour' => 'int',
        'source' => 'int',
        'pay' => 'int',
        'payCnt' => 'int',
        'payUser' => 'int',
        'withdraw' => 'int',
        'withdrawCnt' => 'int',
        'withdrawUser' => 'int',
        'withdrawFirstAll' => 'int',
        'withdrawFirstUserAll' => 'int',
        'thirdExchange' => 'int',
        'thirdExchangeCnt' => 'int',
        'thirdExchangeUser' => 'int',
        'thirdExchangeFirstAll' => 'int',
        'thirdExchangeFirstUserAll' => 'int',
        'registerUser' => 'int',
        'loginUser' => 'int',
        // 'hbChange' => 'int',
        'hbToBulletCost' => 'int',
        'sceneRunningWater' => 'int',
        'cplCost' => 'int',
        'cplCostAll' => 'int',
        'cpaCost' => 'int',
        'cpaCostAll' => 'int',
        'payFirstOldUser24' => 'int',
        'payFirstOldUser24All' => 'int',
        'payFirstOldUser48' => 'int',
        'payFirstOldUser48All' => 'int',
    ];

    protected $appends = [
        'withdrawFirstUserScale',
        'thirdExchangeFirstUserScale',
        'payFirstOldUser24Cost',
        'payFirstOldUser48Cost',
        'withdrawPayScale',
        'thirdExchangePayScale',
        'spreadCost',
    ];

    /**
     * 首日权益率 (首日权益人数/当日注册数)
     * @return float|int
     */
    public function getWithdrawFirstUserScaleAttribute(): float
    {
        return $this->registerUserAll ? $this->withdrawFirstUserAll/$this->registerUserAll : 0;
    }

    /**
     * 首日积分率 (首日积分人数/当日注册数)
     * @return float|int
     */
    public function getThirdExchangeFirstUserScaleAttribute(): float
    {
        return $this->registerUserAll ? $this->thirdExchangeFirstUserAll/$this->registerUserAll : 0;
    }

    /**
     * 24小时内首次充值成本
     * @return float
     */
    public function getPayFirstOldUser24CostAttribute(): float
    {
        return $this->payFirstOldUser24 ? $this->spreadCost/$this->payFirstOldUser24 : 0;
    }

    /**
     * 48小时内首次充值成本
     * @return float
     */
    public function getPayFirstOldUser48CostAttribute(): float
    {
        return $this->payFirstOldUser48 ? $this->spreadCost/$this->payFirstOldUser48 : 0;
    }

    /**
     * 兑换/充值
     * @return float|int
     */
    public function getWithdrawPayScaleAttribute()
    {
        return $this->pay ? $this->withdraw/$this->pay : 0;
    }

    /**
     * 积分/充值 积分占比
     * @return float|int
     */
    public function getThirdExchangePayScaleAttribute()
    {
        return $this->pay ? $this->thirdExchange/getCurrencyHbScale(true)/$this->pay : 0;
    }

    /**
     * 推广成本
     * @return mixed
     */
    public function getSpreadCostAttribute(): int
    {
        return $this->cplCost + $this->cpaCost;
    }

    /**
     * 按小时统计(单条)
     * @param string $day
     * @param int $hour
     * @param bool $append
     * @return array
     */
    public function getSumDataByHour(string $day, int $hour, bool $append = false): array
    {
        $fields = array_filter($this->fillable, function($field) {
            return !in_array($field, ['day', 'hour', 'source']);
        });
        $groups = ['_id' => '$hour'];
        foreach ($fields as $field) {
            $groups[$field] = [
                '$sum' => '$'.$field,
            ];
        }
        $aggregate = [
            [
                '$match' => [
                    'day' => $day,
                    'hour' => $hour,
                    'source' => [
                        '$ne' => 0,
                    ]
                ],
            ],
            [
                '$group' => $groups,
            ],
        ];
        $res = self::raw(function (Collection $collection) use ($aggregate) {
            return $collection->aggregate($aggregate);
        });

        if (!$res = $res->first()) {
            return [];
        }
        $res = $res->setHidden(['_id']);
        if (!$append) $res = $res->setAppends([]);
        return $res->toArray();
    }

    /**
     * 根据渠道获取数据
     * @param array $source
     * @param string $day
     * @param null $groups
     * @return array
     */
    public function getDataBySource(array $source = [], string $day = '', $groups = null): array
    {
        $fields = array_filter($this->fillable, function($field) {
            return !in_array($field, ['day', 'hour', 'source']);
        });

        if (!$groups) {
            $groups = [
                '_id' => '$hour',
                'day' => [
                    '$last' => '$day'
                ],
                'hour' => [
                    '$last' => '$hour'
                ],
            ];
        }
        foreach ($fields as $field) {
            $groups[$field] = [
                '$sum' => '$'.$field,
            ];
        }
        $match = [
            'day' => $day,
            'source' => [
                '$ne' => 0,
            ],
        ];

        if ($source) {
            $match['source'] = [
                '$in' => array_map('intval', $source),
            ];
        }
        $aggregate = [
            [
                '$match' => $match,
            ],
            [
                '$group' => $groups,
            ],
            [
                '$sort' => [
                    '_id' => -1,
                ],
            ],
        ];
        $res = self::raw(function (Collection $collection) use ($aggregate) {
            return $collection->aggregate($aggregate);
        });
        if (!$res->count()) return [];

        return $res->toArray();
    }
}
